<template>
  <div v-if="show">
    <el-row>
      <el-col :span="24">
        <el-affix>
          <comHeader/>
        </el-affix>
      </el-col>
    </el-row>
    <el-affix :offset="50">
      <div class="search-box">
        <el-row>
          <el-col :span="20" :offset="2">
            <el-input
              v-model="message"
              :disabled="inputDisabled"
              placeholder="请输入您的问题～，按下回车键进行提问！"
            />
            <p class="tips">需要科学上网后才可正常使用</p>
          </el-col>
        </el-row>
      </div>
    </el-affix>
    <el-row>
      <el-col :span="20" :offset="2">
        <div>
          <div v-for="(item, index) in list" :key="index" class="result">
            <el-card class="box-card">
              <div>
                <el-avatar :src="myavatar" />
              </div>
              <div>{{item.message}}</div>
              <el-divider />
              <div>
                <el-avatar :src="openai" />
                <img
                  v-if="inputDisabled && index==list.length-1"
                  :src="loading"
                  style="width: 50px;"
                />
              </div>
              <div v-html="item.answerMarked"></div>
            </el-card>
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>
  
  <script>
import comHeader from "@/components/Header.vue";
import { fetchEventSource } from "@microsoft/fetch-event-source";
import { ElMessage } from "element-plus";
import * as config from "@/utils/config";
import imgMyavatar from "../assets/myavatar.jpeg";
import imgOpenai from "../assets/openai.png";
import imgLoading from "../assets/loading.gif";
import MarkdownIt from "markdown-it";
import hljs from "highlight.js";
import "github-markdown-css/github-markdown.css";
import "highlight.js/styles/atom-one-light.css"; //引入一种语法的高亮
var md = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true,
  highlight: function (str, lang) {
    // 得到经过highlight.js之后的html代码
    let code = md.utils.escapeHtml(str);
    if (lang && hljs.getLanguage(lang)) {
      code = hljs.highlight(lang, str, true).value;
    }
    return `<pre style="overflow:auto" class="hljs"><code>${code}</code></pre>`;
  },
});
export default {
  name: "page-home",
  components: {
    comHeader,
  },
  data() {
    return {
      inputDisabled: false,
      myavatar: imgMyavatar,
      openai: imgOpenai,
      loading: imgLoading,
      message: "",
      list: [],
      show: true,
    };
  },
  created() {
    var that = this;
    document.onkeydown = function () {
      let key = window.event.keyCode;
      if (key != 13 || that.inputDisabled) return;
        that.getOpenAIResultStreamApi();
    };
  },
  mounted() {
    let session = sessionStorage.getItem("list");
    this.list = session ? JSON.parse(session) : [];
    this.handleScrollBottom();
  },
  methods: {
    async getOpenAIResultStreamApi() {
      let that = this;
      if (!that.message.length) {
        ElMessage.error("请输入文字！");
        return;
      }
      that.inputDisabled = true;
      that.list.push({
        message: that.message,
        answer: "AI思考中...",
        answerMarked: "AI思考中...",
      });
      that.handleScrollBottom();
      let messages = [{ role: "user", content: that.message }];
      const apiKey = config.ApiKey;
      let url = config.OpenAiBasicUrl + config.OpenAIChat;

      // 创建一个新的 AbortController
      const abortController = new AbortController();

      await fetchEventSource(url, {
        method: "POST",
        body: JSON.stringify({
          model: config.Model,
          messages,
          temperature: 0.3,
          max_tokens: 1000,
          stream: true,
        }),
        headers: {
          Authorization: `Bearer ${apiKey}`,
          "Content-Type": "application/json",
          Accept: "application/json",
        },
        signal: abortController.signal,
        async onopen(response) {
          if (response.ok) return;
          if (response.status === 429) {
            ElMessage.error("请求的 key 超出限制！");
          } else if (response.status === 401) {
            ElMessage.error("请求的 API KEY 无效！");
          } else {
            ElMessage.error("请求出错");
          }
        },
        onmessage(msg) {
          if (msg.data !== "[DONE]") {
            const { choices } = JSON.parse(msg.data);
            if (choices[0].delta.content) {
              if (that.list[that.list.length - 1].answer == "AI思考中...") {
                that.list[that.list.length - 1].answer = "";
              }
              that.list[that.list.length - 1].answer +=
                choices[0].delta.content;
              that.list[that.list.length - 1].answerMarked = md.render(
                that.list[that.list.length - 1].answer
              );
              that.handleScrollBottom();
            }
          }
        },
        onclose() {
          that.inputDisabled = false;
          that.message = "";
          that.saveList();
        },
        onerror() {
          that.list[that.list.length - 1].answer = "出现问题了，回答失败！";
        },
      });
    },
    saveList() {
      sessionStorage.setItem("list", JSON.stringify(this.list));
    },
    handleScrollBottom() {
      this.$nextTick(function () {
        setTimeout(() => {
          const height = document.documentElement.scrollHeight;
          document.documentElement.scrollTop = height;
        }, 100);
      });
    },
  },
};
</script>

<style>
.search-box {
  width: 100%;
  height: 42px;
  padding: 10px 0;
  background-color: #ffffff;
}
.result {
  margin: 10px 0;
}
.chat-box div {
  display: inline-block;
}
.avatar {
  width: 40px;
  height: 40px;
}
.text {
  width: 100%;
}
.tips {
  font-size: 12px;
  color: #bbbbbb;
  text-align: center;
  margin: 0;
  margin-top: 2px;
}
</style>